/**
 * Copyright (C) 2010 altuure <altuure [AT] gmail [DOT] com> http://www.altuure.com/projects/yagdao
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.altuure.yagdao.hibernate;

import com.altuure.yagdao.*;
import org.hibernate.*;
import org.hibernate.impl.CriteriaImpl;

import java.io.Serializable;

/**
 * Generic DAO for object DAO.
 * @author altuure
 */
public class GenericHibernateDAO<T, ID extends Serializable> implements GenericDAO<T, ID> {

    /**
     * Handled entity class
     */
    private Class<T> objectClass;
    /**
     * utility to access session
     */
    private HibernateSessionAccessor sessionAccessor;

    /**
     * id field
     */
    private String idProperty;
    private CommonHibernateDAO commonDAO;

    public void setCommonDAO(CommonHibernateDAO commonDAO) {
        this.commonDAO = commonDAO;
    }


    /*
    * (non-Javadoc)
    *
    * @see com.altuure.yagdao.GenericDAO#getObjectClass()
    */
    public Class getObjectClass() {
        return objectClass;
    }

    /**
     * set object class manual
     * @param objectClass object class
     */
    public void setObjectClass(Class objectClass) {
        this.objectClass = objectClass;
    }

    /**
     * get session accessor
     * @return value
     */
    public HibernateSessionAccessor getSessionAccessor() {
        return sessionAccessor;
    }

    /**
     * set session accessor
     * @param sessionAccessor set value
     */
    public void setSessionAccessor(HibernateSessionAccessor sessionAccessor) {
        this.sessionAccessor = sessionAccessor;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.altuure.yagdao.GenericDAO#save(java.lang.Object)
     */
    public void save(Object object) throws HibernateException {

        commonDAO.save(object);

    }

    /**
     * util method for accesing session
     * @return current session
     */
    public Session getSession() {
        return sessionAccessor.getCurrentSession();
    }

    /** LAZY loading **/
    public T load(ID id) throws HibernateException {
        return (T) commonDAO.load(getObjectClass(), id);
    }

    /**
     * fetch with requested fetchs
     **/
    public T fetch(ID id) throws HibernateException {
         return (T) commonDAO.fetch(objectClass, id);

    }

    /**
     * @param criteria root criteria
     * @param daoFetch fetch list
     */
    protected void setFetchModes(Criteria criteria, YFetch daoFetch) {
        if (daoFetch != null) {
            String[] strings = daoFetch.value();
            for (String s : strings) {
                criteria.setFetchMode(s, FetchMode.JOIN);
            }

        }
    }

    /**
     * select and load
     * @see #load(java.io.Serializable)
     **/
    public T get(ID id) throws HibernateException {

        return (T) commonDAO.get(objectClass, id);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.altuure.yagdao.GenericDAO#count()
     */
    public long count() {
       return commonDAO.count(objectClass);
    }

    /**
     * cout the criteria query
     * @param criteria root criteria
     * @return criteria result set count
     */
    public long count(Criteria criteria) {
        return commonDAO.count(criteria);

    }

    /*
     * (non-Javadoc)
     * 
     * @see com.altuure.yagdao.GenericDAO#update(java.lang.Object)
     */
    public void update(Object object) throws HibernateException {

       commonDAO.update(object);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.altuure.yagdao.GenericDAO#deleteById(java.io.Serializable)
     */
    public void deleteById(ID id) throws HibernateException {
       commonDAO.deleteById(objectClass, id);

    }

    /*
     * (non-Javadoc)
     * 
     * @see com.altuure.yagdao.GenericDAO#delete(java.lang.Object)
     */
    public void delete(Object object) throws HibernateException {
       commonDAO.delete(object);
    }



    /**
     * create criteria query
     * @return   created root criteria
     */
    protected Criteria createCriteria() {
        return commonDAO.createCriteria(objectClass);
    }



    protected SearchResultList<T> query(Criteria criteria) {
        return (SearchResultList<T>) commonDAO.query(criteria);
    }

    /**
     * query with given sort and order
     * @param query query
     * @param paging sort and order
     * @return result set
     */
    protected SearchResultList query(Query query, YLimit paging) {
        return commonDAO.query(query, paging);


    }

    /**
     * execute criteria wuth given criteria and sort and order
     * @param criteriaPass criteria
     * @param paging sort and order
     * @return result set
     */
    protected SearchResultList<T> query(Criteria criteriaPass, YPage paging) {
       return (SearchResultList<T>) commonDAO.query(criteriaPass, paging);
    }

    /**
     * setOrders
     * @param criteria root criteria
     * @param paging   paging
     */
    public void setOrders(CriteriaImpl criteria, YPage paging) {
        commonDAO.setOrders(criteria, paging);
    }

    /**
     * set limits for query.
     * @param criteria criteria
     * @param limits limits
     */
    void setLimits(Criteria criteria, YLimit limits) {
       commonDAO.setLimits(criteria, limits);
    }

    /**
     * set Limits of a query
     * @param query query to be limited
     * @param limits limits
     */
    public void setLimits(Query query, YLimit limits) {
      commonDAO.setLimits(query, limits);
    }
    /*
     * (non-Javadoc)
     * 
     * @see com.altuure.yagdao.GenericDAO#loadAll()
     */
    public SearchResultList<T> getAll() {
        return (SearchResultList<T>) commonDAO.getAll(objectClass);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.altuure.yagdao.GenericDAO#getAll(com.altuure.yagdao.DAOPage)
     */
    public SearchResultList<T> getAll(YPage paging) {
        return (SearchResultList<T>) commonDAO.getAll(objectClass,paging);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.altuure.yagdao.GenericDAO#fetchAll()
     */
    public SearchResultList<T> fetchAll() {
        return (SearchResultList<T>) commonDAO.fetchAll(objectClass);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.altuure.yagdao.GenericDAO#fetchAll(com.altuure.yagdao.DAOPage)
     */
    public SearchResultList<T> fetchAll(YPage page) {
      return (SearchResultList<T>) commonDAO.fetchAll(objectClass,page);

    }

    /**
     * returns the id property for given entity
     * @return id proeprty name
     */
    public String getIdProperty() {
        if (idProperty == null)
            idProperty = commonDAO.getIdProperty(objectClass);
        return idProperty;
    }

    /**
     * find the related criteria from root
     * @param rootCriteria root criteria
     * @param strings property array
     * @return regarding criteria
     */
    protected Criteria findCriteria(CriteriaImpl rootCriteria, String[] strings) {
       return commonDAO.findCriteria(rootCriteria, strings);

    }

    public void detach(Object entity) {
        commonDAO.detach(entity);

    }
    public void init(){
        if(commonDAO==null) {
            commonDAO=new CommonHibernateDAO();
            commonDAO.setSessionAccessor(sessionAccessor);
            commonDAO.init();
        }

    }


}
